package io.renren.modules.mvs.easyExcel;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.qiniu.util.StringUtils;
import io.renren.modules.mvs.entity.VehicleEntity;
import io.renren.modules.mvs.entity.ViolationEntity;
import io.renren.modules.mvs.entity.ViolationTypeEntity;
import io.renren.modules.mvs.service.ViolationService;
import lombok.Getter;
import lombok.extern.log4j.Log4j2;

import java.util.*;

import static io.renren.common.utils.Constant.UNPROCESSED;

@Getter
@Log4j2
public class ViolationDataListener extends AnalysisEventListener<ViolationData> {
    private final ViolationService violationService;
    private final Map<Integer, ViolationData> violationDataMap = new HashMap<>();
    private final List<Integer> errorRowIndexList = new ArrayList<>();

    public ViolationDataListener(ViolationService violationService) {
        this.violationService = violationService;
    }

    @Override
    public void invoke(ViolationData violationData, AnalysisContext context) {
        Integer rowIndex = context.readRowHolder().getRowIndex();
        violationDataMap.put(rowIndex, violationData);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        Collection<ViolationData> violationDataList = violationDataMap.values();
        // 车牌号、违章类型名称、处理状态名称获取相应的id/code
        ArrayList<String> plateNumbers = new ArrayList<>();
        ArrayList<String> violationTypeNames = new ArrayList<>();
        violationDataList.forEach(violationData -> {
            plateNumbers.add(violationData.getPlateNumber());
            violationTypeNames.add(violationData.getViolationTypeName());
        });
        Map<String, List<?>> linkedData = violationService.getLinkedData(plateNumbers, violationTypeNames);
        List<VehicleEntity> vehicleList = (List<VehicleEntity>) linkedData.get("vehicleList");
        List<ViolationTypeEntity> violationTypeList = (List<ViolationTypeEntity>) linkedData.get("violationTypeList");

        // 创建违章记录对象，一个一个插入数据库（为了记录哪些数据插入失败，不能使用批量插入）
        violationDataMap.forEach((rowIndex, violationData) -> {
            try {
                ViolationEntity violation = new ViolationEntity();
                // 用户id和机动车id
                for (VehicleEntity vehicle : vehicleList) {
                    if (vehicle.getPlateNumber().equals(violationData.getPlateNumber())) {
                        violation.setUserId(vehicle.getUserId());
                        violation.setVehicleId(vehicle.getId());
                        break;
                    }
                }
                if (violation.getUserId() == null) {
                    throw new Exception("此车牌号对应的机动车不存在");
                }
                if (violationData.getViolationTime().after(new Date())) {
                    throw new Exception("违章时间不能再当前时间之后");
                }
                violation.setViolationTime(violationData.getViolationTime());   // 违章时间
                violation.setViolationAddress(violationData.getViolationAddress()); // 违章地点
                // 违章类型
                for (ViolationTypeEntity violationType : violationTypeList) {
                    if (violationType.getViolationTypeName().equals(violationData.getViolationTypeName())) {
                        violation.setViolationTypeId(violationType.getId());
                        break;
                    }
                }
                if (violation.getViolationTypeId() == null) {
                    throw new Exception("此违章类型不存在");
                }
                violation.setDescription(violationData.getDescription());   // 说明
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(violation.getViolationTime());
                calendar.add(Calendar.DAY_OF_YEAR, 15);
                violation.setViolationDeadline(calendar.getTime()); // 违章截止时间
                violation.setViolationStatus(UNPROCESSED);  // 处理状态
                violation.setCreateTime(new Date());    // 创建时间
                violationService.saveViolation(violation);
            } catch (Exception e) {
                errorRowIndexList.add(rowIndex);
                log.error("第{}行数据导入失败，{}", rowIndex, e.getMessage());
            }
        });
        errorRowIndexList.forEach(violationDataMap::remove);
        errorRowIndexList.sort(Comparator.naturalOrder());

        String joinStr = StringUtils.join(errorRowIndexList, ",");
        log.info("Excel所有数据读取完毕，导入失败数据：第 {} 行", joinStr);
    }

    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        Integer rowIndex = context.readRowHolder().getRowIndex();
        errorRowIndexList.add(rowIndex);
        log.error("第{}行数据导入失败，{}", rowIndex, exception.getMessage());
    }


}
